/******************************************************************************
 * Copyright (C) 2015  671643387@qq.com
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the
 * Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
 * more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 *
 *****************************************************************************/

#include "ObjectGuid.h"
#include <sstream>

char const* ObjectGuid::GetTypeName(HighGuid _High)
{
    switch (_High)
    {
    case HIGHGUID_ITEM:         return "Item";
    case HIGHGUID_PLAYER:       return "Player";
    case HIGHGUID_GAMEOBJECT:   return "Gameobject";
    case HIGHGUID_TRANSPORT:    return "Transport";
    case HIGHGUID_UNIT:         return "Creature";
    case HIGHGUID_PET:          return "Pet";
    case HIGHGUID_DYNAMICOBJECT: return "DynObject";
    case HIGHGUID_CORPSE:       return "Corpse";
    case HIGHGUID_MO_TRANSPORT: return "MoTransport";
    default:
        return "<unknown>";
    }
}

std::string ObjectGuid::GetString(void) const
{
    std::ostringstream str;
    str << GetTypeName();

    if (IsPlayer())
    {
        // TODO
        //std::string name;
        //if (sObjectMgr.GetPlayerNameByGUID(*this, name))
        //{ str << " " << name; }
    }

    str << " (";
    if (HasEntry())
    { str << (IsPet() ? "Petnumber: " : "Entry: ") << GetEntry() << " "; }
    str << "Guid: " << GetCounter() << ")";
    return str.str();
}

template<HighGuid _High>
std::uint32_t ObjectGuidGenerator<_High>::Generate(void)
{
    if (NextGuid_ >= ObjectGuid::GetMaxCounter(_High) - 1)
    {
        // TODO
        //sLog.outError("%s guid overflow!! Can't continue, shutting down server. ", ObjectGuid::GetTypeName(high));
        //World::StopNow(ERROR_EXIT_CODE);
    }
    return NextGuid_++;
}

ByteBuffer& operator<< (ByteBuffer& _Buf, ObjectGuid const& _Guid)
{
    _Buf << std::uint64_t(_Guid.GetRawValue());
    return _Buf;
}

ByteBuffer& operator>>(ByteBuffer& _Buf, ObjectGuid& _Guid)
{
    _Guid.Set(_Buf.Read<std::uint64_t>());
    return _Buf;
}

ByteBuffer& operator<< (ByteBuffer& _Buf, PackedGuid const& _Guid)
{
    _Buf.Append(_Guid.PackedGuid_);
    return _Buf;
}

ByteBuffer& operator>>(ByteBuffer& _Buf, PackedGuidReader const& _Guid)
{
    _Guid.GuidPtr->Set(ReadPackGUID(_Buf));
    return _Buf;
}

template std::uint32_t ObjectGuidGenerator<HIGHGUID_ITEM>::Generate();
template std::uint32_t ObjectGuidGenerator<HIGHGUID_PLAYER>::Generate();
template std::uint32_t ObjectGuidGenerator<HIGHGUID_GAMEOBJECT>::Generate();
template std::uint32_t ObjectGuidGenerator<HIGHGUID_TRANSPORT>::Generate();
template std::uint32_t ObjectGuidGenerator<HIGHGUID_UNIT>::Generate();
template std::uint32_t ObjectGuidGenerator<HIGHGUID_PET>::Generate();
template std::uint32_t ObjectGuidGenerator<HIGHGUID_DYNAMICOBJECT>::Generate();
template std::uint32_t ObjectGuidGenerator<HIGHGUID_CORPSE>::Generate();